package org.viva.util.wx;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.commons.lang.StringUtils;
import org.viva.core.Log;

import net.sf.json.JSONObject;

public final class HTTPUtils {

    private static final int readTimeOut    = 10 * 1000;
    private static final int connectTimeout = 10 * 1000;

    private static URL                 url;
    private static Map<String, Object> access_tokenMap = new HashMap<String, Object>();
    private static Long                expires_in      = 0l;
    private static ExecutorService     execServ        = Executors.newFixedThreadPool(10);

    private HTTPUtils() {
    }

    /**
     * 异步请求GET
     * 
     * @param urlAddress
     * @author LUYANFENG @ 2015年7月9日
     */
    public static void doThreadGet(final String urlAddress) {
        execServ.execute(new Runnable() {
            @Override
            public void run() {
                String doGet = doGet(urlAddress);
                Log.debug("## 异步执行doGet：" + doGet);
            }
        });
    }

    /**
     * 异步请求POST
     * 
     * @param urlAddress
     * @param params
     * @author LUYANFENG @ 2015年7月9日
     */
    @SuppressWarnings("unchecked")
    public static void doThreadPost(final String urlAddress, final Map<String, Object>... params) {
        execServ.execute(new Runnable() {
            @Override
            public void run() {
                String doPost = doPost(urlAddress, params);
                Log.debug("## 异步执行doPost：" + doPost);
            }
        });
    }

    /**
     * 异步请求POST json
     * 
     * @param urlAddress
     * @param jsonstr
     * @author LUYANFENG @ 2015年7月9日
     */
    public static void doThreadJsonPost(final String urlAddress, final String jsonstr) {
        execServ.execute(new Runnable() {
            @Override
            public void run() {
                Log.debug("有新线程请求");
                String doJsonPost = doJsonPost(urlAddress, jsonstr);
                Log.debug("## 异步执行doJsonPost：" + doJsonPost);
            }
        });
    }

    // 向服务器发送get请求
    public static String doGet(String urlAddress) {
        try {
            Log.debug("url : " + urlAddress);
            url = new URL(urlAddress);
            HttpURLConnection uRLConnection = (HttpURLConnection) url.openConnection();
            uRLConnection.setRequestMethod("GET");
            uRLConnection.setReadTimeout(readTimeOut);
            uRLConnection.setConnectTimeout(connectTimeout);
            return getResponse(uRLConnection);
        } catch (MalformedURLException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    // 向服务器发送post请求
    @SuppressWarnings("unchecked")
    public static String doPost(String urlAddress, Map<String, Object>... params) {
        try {
            Log.debug("url : " + urlAddress);
            url = new URL(urlAddress);
            HttpURLConnection uRLConnection = (HttpURLConnection) url.openConnection();
            uRLConnection.setDoInput(true);
            uRLConnection.setDoOutput(true);
            uRLConnection.setRequestMethod("POST");
            uRLConnection.setUseCaches(false);
            uRLConnection.setInstanceFollowRedirects(false);
            uRLConnection.setReadTimeout(readTimeOut);
            uRLConnection.setConnectTimeout(connectTimeout);
            // uRLConnection.setRequestProperty("Content-Type",
            // "application/x-www-form-urlencoded");
            uRLConnection.connect();

            DataOutputStream out = new DataOutputStream(uRLConnection.getOutputStream());
            final StringBuilder content = new StringBuilder();
            if (params != null && params.length > 0) {
                for (Map<String, Object> map : params) {
                    for (Map.Entry<String, Object> m : map.entrySet()) {
                        content.append("&").append(m.getKey()).append("=").append(m.getValue());
                    }
                }
            }
            out.write(content.toString().getBytes("utf-8"));
            out.flush();
            out.close();

            return getResponse(uRLConnection);
        } catch (MalformedURLException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    // 向服务器发送post请求
    public static String doJsonPost(String urlAddress, String params) {
        try {
            Log.debug("url : " + urlAddress);
            url = new URL(urlAddress);
            HttpURLConnection uRLConnection = (HttpURLConnection) url.openConnection();
            uRLConnection.setDoInput(true);
            uRLConnection.setDoOutput(true);
            uRLConnection.setRequestMethod("POST");
            uRLConnection.setUseCaches(false);
            uRLConnection.setInstanceFollowRedirects(false);
            uRLConnection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
            uRLConnection.setReadTimeout(readTimeOut);
            uRLConnection.setConnectTimeout(connectTimeout);

            if (StringUtils.isNotBlank(params)) {
                Log.debug("------------ params -----------\n" + params);
                Map<String, List<String>> requestProperties = uRLConnection.getRequestProperties();
                for (Map.Entry<?, ?> m : requestProperties.entrySet()) {
                    Log.debug(String.format("%1$20s : %2$s", m.getKey(), m.getValue()));
                }
                Log.debug(" http url :" + uRLConnection.getURL());

                uRLConnection.connect();

                DataOutputStream out = new DataOutputStream(uRLConnection.getOutputStream());
                out.write(params.getBytes("UTF-8"));
                out.close();

            }

            return getResponse(uRLConnection);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static String getResponse(HttpURLConnection uRLConnection) throws IOException {
        InputStream is = uRLConnection.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is, "utf-8"));
        String response = "";
        String readLine = null;
        while ((readLine = br.readLine()) != null) {
            response = response + readLine;
        }
        uRLConnection.disconnect();
        is.close();
        br.close();

        return response;
    }

    /**
     * @param accessTokenUrl
     * @author : LUYANFENG @ 2015年5月27日 access_token的有效期目前为2个小时，定时刷新。
     */
    @SuppressWarnings("unchecked")
    public static Map<String, Object> getAccess_token(final String accessTokenUrl) {
        synchronized (Map.class) {
            if (!access_tokenMap.isEmpty()) {
                Log.debug("access_token = " + access_tokenMap.get("access_token"));
                return Collections.unmodifiableMap(access_tokenMap);
            }
            try {
                String text = doGet(accessTokenUrl);
                Map<String, Object> readValue = JSONObject.fromObject(text);
                access_tokenMap.putAll(readValue);
                Log.debug("-- 申请到新的token：" + access_tokenMap.get("access_token"));
                Thread t = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            expires_in = Long.valueOf(access_tokenMap.get("expires_in").toString());
                            Thread.sleep(expires_in - 200);
                            String text = doGet(accessTokenUrl);
                            Map<String, Object> readValue = JSONObject.fromObject(text);
                            access_tokenMap.putAll(readValue);
                            Log.debug("-- 申请到新的token：" + access_tokenMap.get("access_token"));

                        } catch (Exception e) {
                            Log.debug("-- 申请token时出错：" + e.getMessage());
                        }
                    }
                });
                t.setName("t_申请account_token");
                t.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return Collections.unmodifiableMap(access_tokenMap);
    }
}
